﻿<!DOCTYPE HTML>
<html lang="zh">
<head>
<title>Critical - 语法 &amp; 使用 | AutoHotkey v2</title>
<meta name="description" content="The Critical statement prevents the current thread from being interrupted by other threads, or enables it to be interrupted." />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../static/theme.css" rel="stylesheet" type="text/css" />
<script src="../static/content.js" type="text/javascript"></script>
</head>
<body>

<h1>Critical</h1>

<p>防止<a href="../misc/Threads.htm">当前线程</a>被其他线程中断, 或使其能够被中断.</p>

<pre class="Syntax">
<span class="func">Critical</span> <span class="optional">OnOffNumeric</span></pre>

<h2 id="Parameters">参数</h2>
<dl>
  <dt>OnOffNumeric</dt>
  <dd>
    <p>类型: <a href="../Concepts.htm#strings">字符串</a>或<a href="../Concepts.htm#numbers">整数</a></p>
    <p>如果参数为空或省略, 默认为 <em>On</em>. 否则, 请指定以下之一:</p>
    <p><strong>On:</strong> 设置<a href="../misc/Threads.htm">当前线程</a>为关键的, 这意味着它不会被其他线程中断.</p>
    <p><strong>Off:</strong> 当前线程立即成为可中断的, 无论 <a href="Thread.htm#Interrupt">Thread Interrupt</a> 的设置如何. 有关详情, 请参阅 <a href="#Off">Critical Off</a>.</p>
    <p><strong>(数字):</strong> 指定一个正数来打开 Critical, 但同时也会改变检查内部消息队列的时间间隔. 有关详情, 请参阅<a href="#Interval">消息检查间隔</a>. 指定 0 关闭 Critical. 指定 -1 将启用 Critical, 但禁用消息检查.</p>
  </dd>
</dl>

<h2 id="Return_Value">返回值</h2>
<p>类型: <a href="../Concepts.htm#numbers">整数</a></p>
<p>函数返回以前的设置(值 <a href="../Variables.htm#IsCritical">A_IsCritical</a> 将在调用函数之前返回); 如果 Critical 为 Off, 则为 0, 否则为大于零的整数.</p>

<h2 id="Behave">关键线程的行为</h2>
<p>Critical 线程是 <em>不可中断的</em>; 有关详情, 请参阅<a href="../misc/Threads.htm#Behave">线程</a>.</p>
<p>关键线程在显示 <a href="MsgBox.htm">MsgBox</a> 或其他对话框时, 会变成可中断的. 但是, 与 <a href="Thread.htm#Interrupt">Thread Interrupt</a> 不同, 在用户解除对话框后这个线程会再恢复为关键的.</p>

<h2 id="Off">Critical Off</h2>
<p>当缓冲的事件等待启动新的线程时, 使用 <code>Critical "Off"</code> 不会导致立即中断当前线程, 而会经过平均 5ms 才发生中断. 这会导致在中断前有超过 99.999&nbsp;% 的可能执行了至少一行 <code>Critical "Off"</code> 后面的代码. 可通过使用像 <code><a href="Sleep.htm">Sleep</a> -1</code> 或 <a href="WinWait.htm">WinWait</a> 一个尚不存在的窗口这样的延迟手段立即产生强制中断.</p>
<p><code>Critical "Off"</code> 会取消当前线程的不可中断性周期, 即使该线程不是关键线程, 因此会让像 <a href="GuiOnEvent.htm#Size">Size</a> 这样的事件更快或更可预测地被处理.</p>

<h2 id="Settings">Thread 设置</h2>
<p>如何保存和还原当前的 Critical 设置, 请参阅 <a href="../Variables.htm#IsCritical">A_IsCritical</a>. 但是, 由于 Critical 是特定于线程的设置, 因此当关键线程结束时, 底层/恢复的线程(如果有的话) 将自动是非关键线程. 因此, 不需要在结束线程之前执行 <code>Critical "Off"</code>.</p>
<p>如果在<a href="../Scripts.htm#auto">自动执行线程</a>中没有使用 Critical, 所有的线程将会以非关键线程启动(尽管 <a href="Thread.htm#Interrupt">Thread Interrupt</a> 的设置仍然有效). 相比之下, 如果自动执行线程打开了 Critical 但随后并没有关闭过它, 每个新启动的<a href="../misc/Threads.htm">线程</a>(如 <a href="../Hotkeys.htm">热键</a>, <a href="Menu.htm">自定义菜单项</a>或<a href="SetTimer.htm">计时器</a>子程序) 都会以关键线程方式启动.</p>
<p>函数 <a href="Thread.htm#NoTimers">Thread NoTimers</a> 类似于 Critical, 除了它仅阻止被<a href="SetTimer.htm">计时器</a>中断.</p>

<h2 id="Interval">消息检查间隔</h2>
<p>指定一个正数作为首个参数(例如 <code>Critical 30</code>) 将会打开 Critical, 但同时也会改变检查内部消息队列的最小时间间隔(以 ms 毫秒计). 如果未指定该参数, 在 Critical 打开的状态下, 默认为 16&nbsp;ms, 在 Critical 关闭状态下, 每 5&nbsp;ms 检查一次. 延长时间间隔会推迟消息/事件的到达, 给出更多的时间让<a href="../misc/Threads.htm">当前线程</a>结束. 这会减少某些 <a href="OnMessage.htm">OnMessage 回调</a>和 <a href="GuiOnEvent.htm">GUI events</a> 因为 "线程已运行" 而丢失的可能性. 然而, 像 <a href="Sleep.htm">Sleep</a> 和 <a href="WinWait.htm">WinWait</a> 这样的等待型函数则无视此设定而照常检查消息(一个解决办法是 <code>DllCall("Sleep", "UInt", 500)</code>).</p>
<p>此设置影响如下:</p>
<ul>
  <li>抢先消息检查, 可能发生在每一行代码执行之前.</li>
  <li>在 <a href="Send.htm">Send</a>, 文件和下载操作期间定期检查消息.</li>
</ul>
<p>当脚本暂停或等待时, 它不会影响消息检查的频率.</p>
<p>因为系统滴答计数的间隔通常为 15.6 毫秒, 所以最小增量值通常至少为 15 或 16. 自上次检查以来的持续时间必须 <em>超过</em> 设置的间隔, 以便进行另一次检查. 例如, 设置为 16 要求滴答计数更改为 17 或更大. 由于消息检查可以在 15.6 毫秒窗口内的任何时间发生, 因此在 1 到 16 之间的任何设置都可以允许在单个间隔内进行两次消息检查.</p>
  <p class="note"><strong>注意:</strong> 将消息检查间隔设置的太大会减少对多种事件的响应能力, 例如 <a href="Gui.htm">GUI</a> 窗口的重绘.</p>
<p><code>Critical -1</code> 开启 Critical, 但禁用消息检查. 这并不妨碍程序在执行睡眠, 延迟或等待时检查消息. 在分派消息可能会干扰当前执行的代码的情况下, 例如在 <a href="OnMessage.htm">OnMessage</a> 回调期间处理某些类型的消息时, 它非常有用.</p>

<h2 id="Related">相关</h2>
<p><a href="Thread.htm">Thread (函数)</a>, <a href="../misc/Threads.htm">线程</a>, <a href="_MaxThreadsPerHotkey.htm">#MaxThreadsPerHotkey</a>, <a href="_MaxThreadsBuffer.htm">#MaxThreadsBuffer</a>, <a href="OnMessage.htm">OnMessage</a>, <a href="CallbackCreate.htm">CallbackCreate</a>, <a href="Hotkey.htm">Hotkey</a>, <a href="Menu.htm">Menu 对象</a>, <a href="SetTimer.htm">SetTimer</a></p>

<h2 id="Examples">示例</h2>
<div class="ex" id="ExBasic">
<p><a class="ex_number" href="#ExBasic"></a> 按下热键显示工具提示 3 秒. 由于 Critical, 在此期间启动的任何新线程(例如再次按下热键) 将被推迟, 直到工具提示消失.</p>
<pre>#space::  <em>; Win+Space 热键.</em>
{
    Critical
    ToolTip "No new threads will launch until after this ToolTip disappears."
    Sleep 3000
    ToolTip  <em>; 关闭提示.</em>
    return  <em>; 从热键子程序中返回. 根据定义, 要恢复的任何底层线程都是非关键的.</em>
}</pre>
</div>

</body>
</html>